字符串算法总结
- 数字转字符串
- 字符串逆置(char*、string、折半法逆置字符串、异或法逆置字符串)
- 字符串逆置保持单词不变
- 实现strcpy,strcat,strcmp,strstr
- 最长公共子串(这个博客里讲的比较好,这里我只是自己实现了一下,子串我的博客里已经讲过了 http://blog.sina.com.cn/s/blog_54f82cc20100zi4b.html)
- 最长公共子序列(和子串很像,只是状态转移公式不太一样:字符相等arr[i][j]=arr[i-1][j-1]+1;/字符不等arr[i][j]=max(arr[i][j-1],arr[i-1][j]);然后返回arr[len1][len2]就是最长公共子序列的长度;)
- 回文串(和逆置后的字符串是否相等,leetcode有道很难的最短回文串的题目,是加最少的字符使其成为回文串214. Shortest Palindrome博客里有总结,是利用了KMP里的next数组)
- 字符串最后一个单词的长度(华为OJ上的题热门第一- -|||,cin以空格为结束,所以用getline读取字符串,然后从最后找到空格,length减去找到空格的下标减一即可,当然我是用循环做的,为什么都是90分!!怒)
- 大数加法(字符串加法)
- 大数乘法(字符串减法)
#include<iostream> #include<string> #include<assert.h> #include <vector> #include <algorithm> using namespace std; //数字转字符串 string InttoChar(int num) { if (num == 0) return "0"; string res; while (num != 0) { int tmp = num % 10; char ctmp = tmp + '0'; res.push_back(ctmp); num /= 10; } reverse(res.begin(), res.end()); return res; } //字符串逆置 string reversestring(string s1) { if (s1 == "") return s1; string s2 = ""; for (int i = s1.length() - 1; i >= 0; i--) { s2 += s1[i]; } return s2; } //折半法逆置字符串 char* revetsestring(char* s1) { if (s1 == NULL) return s1; int len = strlen(s1); char* p1, *p2; p1 = s1, p2 = s1 + len - 1; char tmp; while (p1 != p2) { tmp = *p1; *p1 = *p2; *p2 = tmp; p1++; p2--; } return s1; } //异或法逆置字符串 char* revetsestr(char* str) { if (str == NULL) return str; char* f = str, *b = str + strlen(str) - 1; while (f<b) { *f ^= *b; *b ^= *f; *f ^= *b; f++; b--; } return str; } //字符串逆置单词内部顺序不变 char* ReverseWords(char* s1) { int len = strlen(s1); if (s1 == NULL || len == 1) return s1; int i = len - 1, j = len; //ij记录单词的位置 int t = 0; //暂存已经录入单词的位置 char* res = new char[len + 1]; //len不包含'\0'要申请len+1个 int k = 0; //新字符串的位置 while (i>0) { while (s1[i] != ' '&&i != 0) i--; t = i; if (i != 0) { i++; while (i<j) { res[k++] = s1[i++]; } res[k++] = ' '; j = t; i = t - 1; } else { while (i<j) { res[k++] = s1[i++]; } i = t; } } res[len] = '\0'; return res; } //分别实现strcpy,strcat,strcmp,strstr //strcpy需要一个指针记录开始的位置 char* stringcpy(char* des, char* src) { if (src == NULL) return src; int len = strlen(src); des = new char[len + 1]; char* res = des; while (*src != '\0') *des++ = *src++; *des = '\0'; return res; } //strcat,strcat需要des保证可以容纳src,我们这里不需要 char* stringcat(char* des, char*src) { if (src == NULL) return des; int len1 = strlen(des); int len2 = strlen(src); char* newstr = new char[len1 + len2 + 1]; char* res = newstr; while (*des != '\0') *newstr++ = *des++; while (*src != '\0') *newstr++ = *src++; *newstr = '\0'; return res; } //strcmp,使用assert要包含其头文件assert.h不满足assert条件会报错 int stringcmp(char* s1, char* s2) { assert((s1 != NULL) && (s2 != NULL)); while (*s1&&*s2 && (*s1 == *s2)) { s1++; s2++; } return *s1 - *s2; } //strstr leetcode有原题,做过 bool samestr(char* s1, char* s2) { if (strlen(s1) != strlen(s2)) return false; while (*s1) { if (*s1 == *s2) { s1++; s2++; } else return false; } return true; } char* stringstr(char* s1, char* s2) { if (s1 == NULL || s1 == NULL) return NULL; int len1 = strlen(s1); int len2 = strlen(s2); if (len2>len1) return NULL; if (len1 == len2) { if (samestr(s1, s2)) return s1; else return NULL; } for (int i = 0; i<len1;) { char* tmp = NULL; for (int j = 0; j<len2; j++) tmp += s1[i + j]; tmp += '\0'; if (samestr(tmp, s2)) return s1 + i; else i++; } return NULL; } //最长公共子串 string MaxSubstring(string& s1, string& s2) { if (s1 == "" || s2 == "") return ""; int len1 = s1.length(); int len2 = s2.length(); int arraystr[100][100] = { 0 };//then the max length of string is 1000 for (int i = 0; i<len1; i++) { for (int j = 0; j<len2; j++) { if (s1[i] == s2[j]) { if (i == 0 || j == 0) arraystr[i][j] == 1; else arraystr[i][j] = arraystr[i - 1][j - 1] + 1; } else arraystr[i][j] = 0; } } int maxlen = 0; int maxindex = 0; for (int i = len1 - 1; i >= 0; i--) { for (int j = len2 - 1; j >= 0; j--) { if (arraystr[i][j]>maxlen) { maxlen = arraystr[i][j]; maxindex = j; } } } string res = ""; for (int k = maxindex - maxlen + 1; k <= maxindex; k++) res += s2[k]; return res; } //最长公共子序列长度 int Maxsubsequencelength(string& s1, string& s2) { if (s1 == "" || s2 == "") return 0; int arraystr[1010][1010] = { { 0,0 } }; int len1 = s1.length(); int len2 = s2.length(); for (int i = 1; i <= len1; i++) { for (int j = 1; j <= len2; j++) { if (s1[i - 1] == s2[j - 1]) arraystr[i][j] = arraystr[i - 1][j - 1] + 1; else arraystr[i][j] = max(arraystr[i - 1][j], arraystr[i][j - 1]); } } return arraystr[len1][len2]; } string Maxsubsequence(string& s1, string& s2) { //输入时字符串长的那个为第一参数 string res = ""; if (s1 == "" || s2 == "") return res; int arraystr[100][100] = { { 0,0 } }; int len1 = s1.length(); int len2 = s2.length(); for (int i = 1; i <= len1; i++) { for (int j = 1; j <= len2; j++) { if (s1[i - 1] == s2[j - 1]) arraystr[i][j] = arraystr[i - 1][j - 1] + 1; else arraystr[i][j] = max(arraystr[i - 1][j], arraystr[i][j - 1]); } } for (int i = len1; i >= 0;) { for (int j = len2; j >= 0;) { if (arraystr[i][j]>max(max(arraystr[i - 1][j], arraystr[i][j - 1]), arraystr[i - 1][j - 1])) { res = s1[i] + res; i--; j--; } else { if (arraystr[i][j] == arraystr[i - 1][j - 1]) { i--; j--; } else if (arraystr[i][j] == arraystr[i - 1][j]) i--; else if (arraystr[i][j] == arraystr[i][j - 1]) j--; } } } return res; } //最后一个单词的长度 int lastword(string s1) { if (s1 == "") return 0; int len = s1.length(); int i = len - 1; int res = 0; while (i >= 0 && s1[i] == ' ') { i--; } while (i >= 0 && s1[i] != ' ') { i--; res++; } return res; } int lastwordlen(string s1) { getline(cin, s1); if (s1 == "") cout << 0 << endl; return s1.length() - s1.rfind(' ') - 1; } //回文串 bool isPalindrome(string s1) { string s2 = s1; reverse(s2.begin(), s2.end()); if (s1 == s2) return true; else return false; } //字符串大数加法 string stringadd(string& s1, string& s2) { int len1 = s1.length(); int len2 = s2.length(); if (len1 == 0) return s2; if (len2 == 0) return s1; int mlen = max(len1, len2); int* arr1 = new int[mlen];//把字符串数字转换成数组存储,在进行加和然后转成字符串 int* arr2 = new int[mlen]; int index = mlen - 1; for (int i = len1 - 1, j = len2 - 1; i >= 0 || j >= 0; index--) { if (i >= 0) arr1[index] = s1[i--] - '0'; else arr1[index] = 0; if (j >= 0) arr2[index] = s2[j--] - '0'; else arr2[index] = 0; } int* res = new int[mlen + 1]; int carr = 0; int k = mlen - 1, l = mlen; while (k >= 0) { int tmp = arr1[k] + arr2[k] + carr; carr = tmp / 10; res[l--] = tmp % 10; k--; } if (carr != 0) res[0] = carr; else res[0] = 0; string ret = ""; for (int i = 0; i <= mlen; i++) { if (res[i] == 0) continue; char c = '0' + res[i]; ret = ret + c; } return ret; } //字符串大数乘法 char* MultiString(char* str1, char* str2) { int len1 = strlen(str1), len2 = strlen(str2); if (len2>len1) { //len1,str1对应较长的字符串 char* temp = str1; int temp1 = len1; str1 = str2; str2 = temp; len1 = len2; len2 = temp1; } char* ret = new char[len1 + len2]; memset(ret, '0', sizeof(char)*(len1 + len2 - 1)); //初始化字符串 ret[len1 + len2 - 1] = '\0'; if (len1 == 0 || len2 == 0) return ret; int temp1 = 0, temp2 = 0; for (int i = len2 - 1; i >= 0; i--) { int carry = 0; for (int j = len1 - 1; j >= 0; j--) { int sum = ret[i + j] - '0'; if (carry>0) sum += carry; temp1 = str1[j] - '0'; temp2 = str2[i] - '0'; sum += temp1*temp2; if (sum >= 10) { carry = sum / 10; } else carry = 0; ret[i + j] = sum % 10 + '0'; //规格化处理 if (j == 0 && carry>0) //最高位以后还有可能进位 ret[i - 1] += carry; } cout << i << " " << ret << endl; } char* p = ret; while (*p == '0') //如果前面有0,从第一位不是0开始输出 p++; cout << p << endl; return p; } int main() { int num = 1234569; string res = InttoChar(num); cout << res << endl; char* test = "guofei is a student in SEU!"; string test1 = "helloworld"; char* test2 = "happyforever"; cout << reversestring(test2) << endl; cout << reversestring(test1) << endl; cout << ReverseWords(test) << endl; char* s1, *s2 = "cpy this string"; cout << stringcpy(s2, s2) << endl; cout << stringcmp(test, test2) << endl; char* s3 = "auti"; char* s4 = "beautiful girl"; if (stringstr(s3, s4)) cout << "fei zi chuan" << endl; else cout << "zichuan" << endl; //his problem is really tricky, i try to cout NULL and i fix bug just for this little error makes me very wordless string s5 = "ade"; string s6 = "abcde"; string res1 = MaxSubstring(s5, s6); cout << res1 << endl; cout << Maxsubsequence(s6, s5) << endl; string s7 = "accba"; cout << isPalindrome(s7) << endl; return 0; }